package org.sample.springboot.validator;

import java.lang.reflect.Field;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.sample.springboot.util.ReflectUtils;
import org.sample.springboot.util.ReflectUtils.ReflectResult;
import org.sample.springboot.validator.constraints.optional.fieldname.FieldNameOptionalConstraint;

public class FieldNameOptionalValidator extends OptionalValidator
		implements ConstraintValidator<FieldNameOptionalConstraint, Object> {

	private String enableFieldName;
	
	private boolean enableValue;
	
	private boolean enableForNull;
	
	private String optionalFieldName;
	
	@Override
	public void initialize(FieldNameOptionalConstraint constraintAnnotation) {
		enableFieldName = constraintAnnotation.enableFieldName();
		enableValue = constraintAnnotation.enableValue();
		enableForNull = constraintAnnotation.enableForNull();
		optionalFieldName = constraintAnnotation.optionalFieldName();
	}

	@Override
	public boolean isValid(Object value, ConstraintValidatorContext context) {
		if (value == null) {
			return true;
		}

		ReflectResult<Field> enableField = ReflectUtils.getField(value, enableFieldName);
		if (!enableField.isAvailable()) {
			// Fail validation if enable field doesn't exist.
			return false;
		}
		
		ReflectResult<Boolean> enableFieldValue = ReflectUtils.getValue(value, enableField.getResult(), Boolean.class);
		if (!enableFieldValue.isAvailable()) {
			// Fail validation if enable field isn't Boolean.
			return false;
		}
		
		boolean isEnabled = false;
		if (enableFieldValue.getResult() == null) {
			if (enableForNull) {
				isEnabled = true;
			}
		} else {
			if (enableFieldValue.getResult().equals(enableValue)) {
				isEnabled = true;
			}
		}

		ReflectResult<Field> optionalField = ReflectUtils.getField(value, optionalFieldName);
		if (!optionalField.isAvailable()) {
			// Fail validation if optional field doesn't exist.
			return false;
		}
		
		ReflectResult<Object> optionalFieldValue = ReflectUtils.getValue(value, optionalField.getResult());

		return isValid(isEnabled, optionalFieldValue.getResult(), this.optionalFieldName, context);
	}

}
